﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Interop;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using Xc.DataAccess.HyperTerminalCore.Models;
using Microsoft.Win32;
using Xc.HyperTerminal.Services;
using Xc.HyperTerminal.ViewModels;
using Xc.DataAccess.Core.Extensions;
using DotNetUI.Controls;

namespace Xc.Logics.HyperTerminalCore.Tcp.Views
{
    /// <summary>
    /// TerminalView.xaml 的交互逻辑
    /// </summary>
    public partial class TerminalView : UserControl
    {
        private readonly TcpClientInfo tcpClientInfo;
        public TerminalView(TcpClientInfo tcpClientInfo)
        {
            InitializeComponent();
            this.tcpClientInfo = tcpClientInfo;
            tcpClientInfo.ReceiveMessage += TcpClientInfo_ClientMessage;
        }

        private void TcpClientInfo_ClientMessage(byte[] arg1, TcpClientInfo arg2,Encoding encoding)
        {
            var chatInfo = new ChatInfo { Caption=arg2.IpAddress, DateTime = DateTime.Now, Alignment = HorizontalAlignment.Left, Content = encoding.GetString(arg1), Status = Status.Success, RespondMessage = null };
            AddLog(chatInfo);
        }

        private void CommandBinding_CanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            if (!string.IsNullOrEmpty(ViewModel.SendText))
            {
                e.CanExecute = true;
            }
            
        }

        private void CommandBinding_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            ViewModel.SendText = string.Empty;
        }

        private void CommandBinding_CanExecute_1(object sender, CanExecuteRoutedEventArgs e)
        {
            if (!string.IsNullOrEmpty(ViewModel.SendText))
            {
                e.CanExecute = true;
            }
        }

        private async void CommandBinding_Executed_1(object sender, ExecutedRoutedEventArgs e)
        {
            await Send(ViewModel.SendText);
            ViewModel.SendText = String.Empty;
        }
        public async void AddLog(ChatInfo chatInfo)
        {
           await this.Dispatcher.InvokeAsync(() => {
                this.ViewModel.ChatInfos.Add(chatInfo);
               ChatLogs.ScrollViewer.ScrollToEnd();
           });
        }
        /// <summary>
        /// 发送图片
        /// </summary>
        /// <param name="fileName"></param>
        /// <returns></returns>
        private async Task<bool> SendImage(string fileName)
{
            var chatInfo = new ChatInfo { Caption = "127.0.0.1", DateTime = DateTime.Now, Alignment = HorizontalAlignment.Right, Content = fileName, Status = Status.Pending, RespondMessage = null,ContentType=DotNetUI.Models.ContentType.Image };
            AddLog(chatInfo);
            var bytes=await  File.ReadAllBytesAsync(fileName);
            var res = await tcpClientInfo.Send(bytes);
            if (res.IsError)
            {
                chatInfo.RespondMessage = res.Message;
            }
            return res.IsSuccess;
        }
        /// <summary>
        /// 发送代码
        /// </summary>
        /// <param name="content"></param>
        /// <param name="langugage"></param>
        /// <returns></returns>
        private async Task<bool> SendCode(string content, Langugage langugage)
        {
            var chatInfo = new ChatInfo { Caption = "127.0.0.1", DateTime = DateTime.Now, Alignment = HorizontalAlignment.Right, Content = content, Status = Status.Pending, RespondMessage = null, ContentType = DotNetUI.Models.ContentType.Code,HightLight= langugage };
            AddLog(chatInfo);
            var res = await tcpClientInfo.Send(content,false);
            return res.IsSuccess;
        }
        private async Task<bool> Send(byte[] message)
        {
            var chatInfo = new ChatInfo {Caption="127.0.0.1", DateTime = DateTime.Now, Alignment = HorizontalAlignment.Right, Content = message.ToHex(), Status = Status.Pending, RespondMessage = null };
            AddLog(chatInfo);
            var res =await tcpClientInfo.Send(message);
            await Task.Delay(10);
            if (res.IsSuccess)       {
                chatInfo.Status = Status.Success;
                return true;
            }
            else
            {
                chatInfo.Status = Status.Failed;
                chatInfo.RespondMessage = res.Message;
                return false;
            }
        }
        public async Task<bool> Send(string message)
        {
            var chatInfo = new ChatInfo { Caption = "127.0.0.1", DateTime = DateTime.Now, Alignment = HorizontalAlignment.Right, Content = message, Status = Status.Pending, RespondMessage = null };
            AddLog(chatInfo);
            var res =await tcpClientInfo.Send(message, this.ViewModel.AppendLine);
            if (res.IsSuccess)
            {
                chatInfo.Status = Status.Success;
                return true;
            }
            else
            {
                chatInfo.Status = Status.Failed;
                chatInfo.RespondMessage = res.Message;
                return false;
            }
        }
        private void CommandBinding_CanExecute_2(object sender, CanExecuteRoutedEventArgs e)
        {
            if (_SendTextBox!=null&&ViewModel.ReturnSend && _SendTextBox.IsFocused)
            {
                if (!string.IsNullOrEmpty(ViewModel.SendText))
                {
                    e.CanExecute = true;
                }
            }
        }

        private void CommandBinding_CanExecute_3(object sender, CanExecuteRoutedEventArgs e)
        {
            if (ViewModel.ChatInfos.Count>0)
            {
                e.CanExecute = true;
            }
        }

        private void CommandBinding_Executed_2(object sender, ExecutedRoutedEventArgs e)
        {
            ViewModel.ChatInfos.Clear();
        }

        private void CommandBinding_CanExecute_4(object sender, CanExecuteRoutedEventArgs e)
        {
            e.CanExecute = true;
        }
        /// <summary>
        /// 发送文件
        /// </summary>
        /// <param name="fileName"></param>
        /// <returns></returns>
        private async Task SendFile(string fileName)
        {

            FileInfo fileInfo = new FileInfo(fileName);
            switch (fileInfo.Extension )
            {
                case ".png":
                case ".jpeg":
                    {
                      await  this.SendImage(fileName);
                    }break;
                default:
                    {
                        await Task.Run(async () =>
                        {
                            var file = File.OpenRead(fileName);
                            byte[] vs = new byte[250];
                            int length = 0;
                            bool SendContinue = false;
                            do
                            {
                                length = file.Read(vs, 0, vs.Length);
                                if (length == 0)
                                {
                                    break;
                                }
                                var buffer = vs.Take(length).ToArray();
                                SendContinue = await Send(buffer);
                            } while (length > 0 && SendContinue == true);
                        });
                    }break;
            }
          
        }
        private async void CommandBinding_Executed_3(object sender, ExecutedRoutedEventArgs e)
        {
            OpenFileDialog openFileDialog=new OpenFileDialog();
            if (openFileDialog.ShowDialog()==true)
            {


             await   SendFile(openFileDialog.FileName);
            }
        }

        private void CommandBinding_CanExecute_5(object sender, CanExecuteRoutedEventArgs e)
        {
            e.CanExecute = true;
        }

        private async void CommandBinding_Executed_4(object sender, ExecutedRoutedEventArgs e)
        {
            OpenFileDialog openFileDialog = new OpenFileDialog();
            if (openFileDialog.ShowDialog() == true)
            {
                try
                {
                    var file = System.IO.File.OpenRead(openFileDialog.FileName);
                    DataHandler dataHandler = new DataHandler(tcpClientInfo, this);
                    await dataHandler.Request("iapprepare", file, async (a, b, c, d, stream) =>
                    {
                        if (string.IsNullOrEmpty(a))
                        {
                            d.Status = Status.Failed;
                            d.RespondMessage = "设备无响应";
                            return;
                        }
                        await OnUpdate(stream, a, b, c, d);
                    });
                }
                catch (Exception err)
                {
                    MessageBox.Show(err.Message,"错误",MessageBoxButton.OK,MessageBoxImage.Error);
                }

            }
        }
        private async Task OnUpdate(FileStream file, string message, TcpClientInfo client,DataHandler dataHandler,ChatInfo chatInfo)
        {
            try
            {
                byte[] vs = new byte[256];
                int length = 0;
                message = message.ToLower();
                if (message.Contains("iap prepare success"))
                {
                    length = file.Read(vs, 0, vs.Length);
                    if (length == 0)
                    {
                        chatInfo.RespondMessage = "无效文件";

                        return;
                    }
                    var buffer = vs.Take(length).ToArray();
                   await this.Dispatcher.InvokeAsync(async() => {
                        ParameterInputView parameterInputView = new ParameterInputView();
                        if (parameterInputView.ShowDialog() == true)
                        {
                            await dataHandler.Request($"iapwrite@0x{parameterInputView.ipadAddress.Text.Trim()},{buffer.ToHex()}", file, async (a, b, c, d, stream) =>
                            {
                                await OnUpdate(stream, a, b, c, d);
                            });
                        }
                    });


                }
                else if (message.Contains("iapwrite") && message.Contains("success"))
                {
                    length = file.Read(vs, 0, vs.Length);
                    if (length == 0)
                    {
                        chatInfo.RespondMessage = "升级成功";

                        return;
                    }
                    var buffer = vs.Take(length).ToArray();
                    var ad = message.Split("@");
                    if (ad.Length > 1)
                    {
                        var fuck = ad[1].Split(",");
                        if (fuck.Length > 2)
                        {
                            var ad1 = fuck[0].Replace("0x", String.Empty);
                            var ad2 = fuck[1].Replace("0x", String.Empty);
                            var bytes1 = ad1.ToHex();
                            var bytes2 = ad2.ToHex();
                            var res = BitConverter.ToUInt32(bytes1.Reverse().ToArray()) + BitConverter.ToUInt32(bytes2.Reverse().ToArray());
                            var final = BitConverter.GetBytes(res).Reverse().ToArray().ToHex();
                            if (res >= file.Length)
                            {
                                chatInfo.RespondMessage = "升级成功";
                                return;
                            }
                            await dataHandler.Request($"iapwrite@0x{final},{BitConverter.ToString(buffer).Replace("-", String.Empty)}", file, async (a, b, c, d, stream) =>
                            {
                                await OnUpdate(stream, a, b, c, d);
                            });
                        }
                    }

                }
                else
                {
                    if (string.IsNullOrEmpty(message))
                    {
                        chatInfo.Status = Status.Pending;
                        chatInfo.RespondMessage = "接收中...";
                    }
                    else
                    {
                        chatInfo.Status = Status.Failed;
                        chatInfo.RespondMessage = message;

                    }
                }
            }
            catch (Exception err)
            {
                chatInfo.Status = Status.Failed;
                chatInfo.RespondMessage = err.Message;
            }

        }

        private void CommandBinding_CanExecute_6(object sender, CanExecuteRoutedEventArgs e)
        {
            e.CanExecute = true;
        }

        private async void CommandBinding_Executed_5(object sender, ExecutedRoutedEventArgs e)
        {
            OpenFileDialog openFileDialog = new OpenFileDialog();
            openFileDialog.Filter = "CSharp|*.cs";
            if (openFileDialog.ShowDialog() == true)
            {
                try
                {
                    var file = System.IO.File.ReadAllText(openFileDialog.FileName);
                    await SendCode(file,Langugage.CSharp);
                }
                catch (Exception err)
                {
                    MessageBox.Show(err.Message, "错误", MessageBoxButton.OK, MessageBoxImage.Error);
                }

            }
        }
    }
}
